<!--

    Copyright © 2016-2025 The Thingsboard Authors

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

-->
<mat-drawer-container hasBackdrop="false" class="tb-absolute-fill">
  <mat-drawer *ngIf="entitiesTableConfig.detailsPanelEnabled"
              class="tb-details-drawer mat-elevation-z4"
              #drawer
              mode="over"
              position="end"
              [opened]="isDetailsOpen">
    <tb-entity-details-panel
      #entityDetailsPanel
      [entitiesTableConfig]="entitiesTableConfig"
      [entityId]="isDetailsOpen ? dataSource.currentEntity?.id : null"
      (closeEntityDetails)="isDetailsOpen = false; detailsPanelOpened.emit(isDetailsOpen);"
      (entityUpdated)="onEntityUpdated($event)"
      (entityAction)="onEntityAction($event)"
    >
    </tb-entity-details-panel>
  </mat-drawer>
  <mat-drawer-content>
    <div class="mat-padding tb-entity-table tb-absolute-fill">
      <div class="tb-entity-table-content tb-outlined-border flex flex-col">
        <mat-toolbar class="mat-mdc-table-toolbar" [class.!hidden]="textSearchMode || !dataSource.selection.isEmpty()">
          <div class="mat-toolbar-tools">
            <div class="title-container flex flex-row items-center justify-start xs:flex-col xs:items-start xs:justify-center">
              <span *ngIf="entitiesTableConfig.tableTitle" class="tb-entity-table-title">{{ entitiesTableConfig.tableTitle }}</span>
              <tb-anchor #entityTableHeader></tb-anchor>
              <tb-timewindow *ngIf="entitiesTableConfig.useTimePageLink" [(ngModel)]="timewindow"
                              (ngModelChange)="onTimewindowChange()"
                              asButton strokedButton historyOnly [forAllTimeEnabled]="entitiesTableConfig.forAllTimeEnabled"></tb-timewindow>
            </div>
            <span class="flex-1"></span>
            <div [class.!hidden]="!addEnabled()">
              <ng-container *ngIf="!entitiesTableConfig.addActionDescriptors.length; else addActions">
                <button *ngIf="!entitiesTableConfig.addAsTextButton"
                        mat-icon-button
                        [disabled]="isLoading$ | async"
                        (click)="addEntity($event)"
                        matTooltip="{{ translations.add | translate }}"
                        matTooltipPosition="above">
                  <mat-icon>add</mat-icon>
                </button>
                <button *ngIf="entitiesTableConfig.addAsTextButton"
                        mat-stroked-button color="primary"
                        [disabled]="isLoading$ | async"
                        (click)="addEntity($event)">
                  <mat-icon>add</mat-icon>
                  {{ translations.add | translate }}
                </button>
              </ng-container>
              <ng-template #addActions>
                <ng-container *ngIf="entitiesTableConfig.addActionDescriptors.length === 1; else addActionsMenu">
                  <button *ngIf="!entitiesTableConfig.addAsTextButton && entitiesTableConfig.addActionDescriptors[0].isEnabled()"
                          mat-icon-button
                          [disabled]="isLoading$ | async"
                          (click)="entitiesTableConfig.addActionDescriptors[0].onAction($event)"
                          matTooltip="{{ entitiesTableConfig.addActionDescriptors[0].name }}"
                          matTooltipPosition="above">
                    <tb-icon>{{entitiesTableConfig.addActionDescriptors[0].icon}}</tb-icon>
                  </button>
                  <button *ngIf="entitiesTableConfig.addAsTextButton && entitiesTableConfig.addActionDescriptors[0].isEnabled()"
                          mat-stroked-button color="primary"
                          [disabled]="isLoading$ | async"
                          (click)="entitiesTableConfig.addActionDescriptors[0].onAction($event)">
                    <tb-icon>{{entitiesTableConfig.addActionDescriptors[0].icon}}</tb-icon>
                    {{ entitiesTableConfig.addActionDescriptors[0].name }}
                  </button>
                </ng-container>
                <ng-template #addActionsMenu>
                  <button mat-icon-button [disabled]="isLoading$ | async"
                          matTooltip="{{ translations.add | translate }}"
                          matTooltipPosition="above"
                          [matMenuTriggerFor]="addActionsMenu">
                    <mat-icon>add</mat-icon>
                  </button>
                  <mat-menu #addActionsMenu="matMenu" xPosition="before">
                    <button mat-menu-item *ngFor="let actionDescriptor of entitiesTableConfig.addActionDescriptors"
                            [disabled]="isLoading$ | async"
                            [class.!hidden]="!actionDescriptor.isEnabled()"
                            (click)="actionDescriptor.onAction($event)">
                      <tb-icon matMenuItemIcon>{{actionDescriptor.icon}}</tb-icon>
                      <span>{{ actionDescriptor.name }}</span>
                    </button>
                  </mat-menu>
                </ng-template>
              </ng-template>
            </div>
            <button mat-icon-button [disabled]="isLoading$ | async"
                    [class.!hidden]="!actionDescriptor.isEnabled()" *ngFor="let actionDescriptor of headerActionDescriptors"
                    matTooltip="{{ actionDescriptor.name }}"
                    matTooltipPosition="above"
                    (click)="actionDescriptor.onAction($event)">
              <tb-icon>{{actionDescriptor.icon}}</tb-icon>
            </button>
            <button mat-icon-button [disabled]="isLoading$ | async" (click)="updateData()"
                    matTooltip="{{ 'action.refresh' | translate }}"
                    matTooltipPosition="above">
              <mat-icon>refresh</mat-icon>
            </button>
            <button *ngIf="entitiesTableConfig.searchEnabled"
                    mat-icon-button [disabled]="isLoading$ | async" (click)="enterFilterMode()"
                    matTooltip="{{ translations.search | translate }}"
                    matTooltipPosition="above">
              <mat-icon>search</mat-icon>
            </button>
          </div>
        </mat-toolbar>
        <mat-toolbar class="mat-mdc-table-toolbar" [class.!hidden]="!textSearchMode || !dataSource.selection.isEmpty()">
          <div class="mat-toolbar-tools">
            <button mat-icon-button
                    matTooltip="{{ translations.search | translate }}"
                    matTooltipPosition="above">
              <mat-icon>search</mat-icon>
            </button>
            <mat-form-field class="flex-1">
              <mat-label>&nbsp;</mat-label>
              <input #searchInput matInput
                     [formControl]="textSearch"
                     placeholder="{{ translations.search | translate }}"/>
            </mat-form-field>
            <button mat-icon-button (click)="exitFilterMode()"
                    matTooltip="{{ 'action.close' | translate }}"
                    matTooltipPosition="above">
              <mat-icon>close</mat-icon>
            </button>
          </div>
        </mat-toolbar>
        <mat-toolbar *ngIf="entitiesTableConfig.selectionEnabled" class="mat-mdc-table-toolbar" color="primary" [class.!hidden]="dataSource.selection.isEmpty()">
          <div class="mat-toolbar-tools">
            <span class="tb-entity-table-info">
              {{ translations.selectedEntities | translate:{count: dataSource.selection.selected.length} }}
            </span>
            <span class="flex-1"></span>
            <button mat-icon-button [disabled]="isLoading$ | async"
                    [class.!hidden]="!actionDescriptor.isEnabled" *ngFor="let actionDescriptor of groupActionDescriptors"
                    matTooltip="{{ actionDescriptor.name }}"
                    matTooltipPosition="above"
                    (click)="actionDescriptor.onAction($event, dataSource.selection.selected)">
              <tb-icon>{{actionDescriptor.icon}}</tb-icon>
            </button>
          </div>
        </mat-toolbar>
        <div class="table-container flex-1">
          <table mat-table [dataSource]="dataSource" [trackBy]="trackByEntityId"
                     matSort [matSortActive]="pageLink.sortOrder?.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
            <ng-container matColumnDef="select" sticky>
              <mat-header-cell *matHeaderCellDef style="width: 40px;">
                <mat-checkbox (change)="$event ? dataSource.masterToggle() : null"
                              [checked]="dataSource.selection.hasValue() && (dataSource.isAllSelected() | async)"
                              [indeterminate]="dataSource.selection.hasValue() && !(dataSource.isAllSelected() | async)">
                </mat-checkbox>
              </mat-header-cell>
              <mat-cell *matCellDef="let entity">
                <mat-checkbox (click)="$event.stopPropagation()"
                              [class.!hidden]="!entitiesTableConfig.entitySelectionEnabled(entity)"
                              (change)="$event ? dataSource.selection.toggle(entity) : null"
                              [checked]="dataSource.selection.isSelected(entity)">
                </mat-checkbox>
              </mat-cell>
            </ng-container>
            <ng-container [matColumnDef]="column.key" *ngFor="let column of entityColumns; trackBy: trackByColumnKey;">
              <mat-header-cell [class.mat-number-cell]="column.isNumberColumn"
                               [class.lt-lg:!hidden]="column.mobileHide"
                               *matHeaderCellDef [style]="headerCellStyle(column)" mat-sort-header [disabled]="!column.sortable">
                {{ column.ignoreTranslate ? column.title : (column.title | translate) }} </mat-header-cell>
              <mat-cell [class.mat-number-cell]="column.isNumberColumn"
                        [class.cell-action]="column.actionCell?.type === cellActionType.COPY_BUTTON"
                        [class.lt-lg:!hidden]="column.mobileHide"
                        *matCellDef="let entity; let row = index"
                        [matTooltip]="cellTooltip(entity, column, row)"
                        #cellMatTooltip="matTooltip"
                        matTooltipPosition="above"
                        [style]="cellStyle(entity, column, row)">
                <ng-container [ngSwitch]="column.type">
                  <ng-template [ngSwitchCase]="'link'">
                    <a *ngIf="column.entityURL(entity) as detailsPageURL; else defaultContent"
                       [routerLink]="detailsPageURL" [innerHTML]="cellContent(entity, column, row)"
                       (click)="$event.stopPropagation();"></a>
                  </ng-template>
                  <ng-template [ngSwitchCase]="'entityChips'">
                    <tb-entity-chips [entity]="entity" [key]="column.key"
                                     [detailsPagePrefixUrl]="column.entityURL ? column.entityURL(entity) : ''"></tb-entity-chips>
                  </ng-template>
                  <ng-template #defaultContent ngSwitchDefault>
                    <span [innerHTML]="cellContent(entity, column, row)"></span>
                  </ng-template>
                </ng-container>
                <ng-template [ngIf]="column.actionCell">
                  <ng-container [ngSwitch]="column.actionCell.type">
                    <ng-template [ngSwitchCase]="cellActionType.COPY_BUTTON">
                      <tb-copy-button
                        class="copy-button"
                        [disabled]="isLoading$ | async"
                        [class.!hidden]="!column.actionCell.isEnabled(entity)"
                        [copyText]="column.actionCell.onAction(null, entity)"
                        tooltipText="{{ column.actionCell.nameFunction ? column.actionCell.nameFunction(entity) : column.actionCell.name }}"
                        tooltipPosition="above"
                        (mouseover)="cellMatTooltip.hide()"
                        (mouseleave)="cellMatTooltip.show()"
                        [icon]="column.actionCell.icon"
                        [style]="column.actionCell.style">
                      </tb-copy-button>
                    </ng-template>
                    <ng-template ngSwitchDefault>
                      <button mat-icon-button [disabled]="isLoading$ | async"
                              [class.!hidden]="!column.actionCell.isEnabled(entity)"
                              matTooltip="{{ column.actionCell.nameFunction ? column.actionCell.nameFunction(entity) : column.actionCell.name }}"
                              matTooltipPosition="above"
                              (click)="column.actionCell.onAction($event, entity)">
                        <tb-icon [style]="column.actionCell.style">
                          {{column.actionCell.icon}}
                        </tb-icon>
                      </button>
                    </ng-template>
                  </ng-container>
                </ng-template>
              </mat-cell>
            </ng-container>
            <ng-container [matColumnDef]="column.key" *ngFor="let column of actionColumns; trackBy: trackByColumnKey;">
              <mat-header-cell *matHeaderCellDef [style]="headerCellStyle(column)" mat-sort-header [disabled]="!column.sortable"> {{ column.title | translate }} </mat-header-cell>
              <mat-cell *matCellDef="let entity; let row = index"
                        [style]="cellStyle(entity, column, row)">
                <button mat-icon-button [disabled]="isLoading$ | async"
                        [class.!hidden]="!column.actionDescriptor.isEnabled(entity)"
                        matTooltip="{{ column.actionDescriptor.nameFunction ? column.actionDescriptor.nameFunction(entity) : column.actionDescriptor.name }}"
                        matTooltipPosition="above"
                        (click)="column.actionDescriptor.onAction($event, entity)">
                  <tb-icon [style]="column.actionDescriptor.style">
                    {{column.actionDescriptor.iconFunction ? column.actionDescriptor.iconFunction(entity) : column.actionDescriptor.icon}}
                  </tb-icon>
                </button>
              </mat-cell>
            </ng-container>
            <ng-container matColumnDef="actions" stickyEnd>
              <mat-header-cell *matHeaderCellDef>
                <ng-container *ngIf="cellActionDescriptors.length">
                  <div class="gt-md:!hidden" style="min-width: 48px;">
                    {{ entitiesTableConfig.actionsColumnTitle ? (entitiesTableConfig.actionsColumnTitle | translate) : '' }}
                  </div>
                  <div class="lt-lg:!hidden"
                       [style.min-width]="(cellActionDescriptors.length * 48) + 'px'">
                    {{ entitiesTableConfig.actionsColumnTitle ? (entitiesTableConfig.actionsColumnTitle | translate) : '' }}
                  </div>
                </ng-container>
              </mat-header-cell>
              <mat-cell *matCellDef="let entity">
                <ng-container *ngIf="cellActionDescriptors.length">
                  <div [class.lt-lg:!hidden]="cellActionDescriptors.length !== 1" class="flex flex-row items-stretch justify-end"
                       [style.min-width]="(cellActionDescriptors.length * 48) + 'px'">
                    <button mat-icon-button [disabled]="(isLoading$ | async) || !actionDescriptor.isEnabled(entity)"
                            *ngFor="let actionDescriptor of cellActionDescriptors"
                            matTooltip="{{ actionDescriptor.nameFunction ? actionDescriptor.nameFunction(entity) : actionDescriptor.name }}"
                            matTooltipPosition="above"
                            (click)="actionDescriptor.onAction($event, entity)">
                      <tb-icon [style]="actionDescriptor.style">
                        {{actionDescriptor.iconFunction ?  actionDescriptor.iconFunction(entity) : actionDescriptor.icon}}
                      </tb-icon>
                    </button>
                  </div>
                  <div [class.!hidden]="cellActionDescriptors.length === 1" class="gt-md:!hidden">
                    <button mat-icon-button
                            (click)="$event.stopPropagation()"
                            [matMenuTriggerFor]="cellActionsMenu">
                      <mat-icon class="material-icons">more_vert</mat-icon>
                    </button>
                    <mat-menu #cellActionsMenu="matMenu" xPosition="before">
                      <button mat-menu-item *ngFor="let actionDescriptor of cellActionDescriptors"
                              [disabled]="isLoading$ | async"
                              [class.!hidden]="!actionDescriptor.isEnabled(entity)"
                              (click)="actionDescriptor.onAction($event, entity)">
                        <tb-icon matMenuItemIcon [style]="actionDescriptor.style">
                          {{actionDescriptor.iconFunction ?  actionDescriptor.iconFunction(entity) : actionDescriptor.icon}}
                        </tb-icon>
                        <span>{{ actionDescriptor.nameFunction ? actionDescriptor.nameFunction(entity) : actionDescriptor.name }}</span>
                      </button>
                    </mat-menu>
                  </div>
                </ng-container>
              </mat-cell>
            </ng-container>
            <mat-header-row [class.mat-row-select]="selectionEnabled" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
            <mat-row [class.!hidden]="dataSource.dataLoading"
                     [class.mat-row-select]="selectionEnabled"
                     [class.mat-selected]="dataSource.selection.isSelected(entity)"
                     [class.tb-current-entity]="dataSource.isCurrentEntity(entity)"
                     [class.tb-pointer]="entitiesTableConfig.rowPointer"
                     *matRowDef="let entity; columns: displayedColumns;" (click)="onRowClick($event, entity)"></mat-row>
          </table>
          <span [class.!hidden]="(isLoading$ | async) || (dataSource.isEmpty() | async) === false || dataSource.dataLoading"
                class="no-data-found flex items-center justify-center">{{ translations.noEntities | translate }}</span>
          <span [class.!hidden]="!dataSource.dataLoading"
                class="no-data-found flex items-center justify-center">{{ 'common.loading' | translate }}</span>
        </div>
        <mat-divider *ngIf="displayPagination"></mat-divider>
        <mat-paginator *ngIf="displayPagination"
                       [length]="dataSource.total() | async"
                       [pageIndex]="pageLink.page"
                       [pageSize]="pageLink.pageSize"
                       [pageSizeOptions]="pageSizeOptions"
                       [hidePageSize]="hidePageSize"
                       showFirstLastButtons></mat-paginator>
      </div>
    </div>
  </mat-drawer-content>
</mat-drawer-container>
